package temp

import (
	"bytes"
	"encoding/base64"
	"github.com/wcharczuk/go-chart/v2"
	"github.com/wcharczuk/go-chart/v2/drawing"
	"math/rand"
	"os"
	"strconv"
	"time"
)

const (
	lineChartXAxisName  = "Date"
	lineChartYAxisName  = "Count"
	lineChartHeight     = 700
	lineChartWidth      = 1280
	colorMultiplier     = 256
	imgStrPrefix        = "data:image/png;base64,"
	pieLabelFormat      = "%v %v"
	barChartTryAgainErr = "invalid data range; cannot be zero"
)

var (
	lineChartStyle = chart.Style{
		Padding: chart.Box{
			Top:  30,
			Left: 150,
		},
	}

	timeFormat = chart.TimeDateValueFormatter
)

type LineYValue struct {
	Name   string
	Values []float64
}

// createLineChart 创建线性图
func createLineChart(title string, endTime time.Time, values []LineYValue) (img string, err error) {
	if len(values) == 0 {
		return
	}
	// 1、计算X轴
	lenX := len(values[0].Values)
	// X轴内容xValues 及 X轴坐标ticks
	var xValues []time.Time
	var ticks []chart.Tick

	for i := lenX - 1; i >= 0; i-- {
		curTime := endTime.AddDate(0, 0, -i)
		xValues = append(xValues, curTime)
		ticks = append(ticks, chart.Tick{Value: getNsec(curTime), Label: timeFormat(curTime)})

	}

	//var annotations []chart.Value2
	//annotations = append(annotations, chart.Value2{
	//	Label:  timeFormat(curTime),
	//	XValue: getNsec(curTime),
	//	YValue: 0,
	//})
	// 2、生成Series
	var series []chart.Series
	for _, yValue := range values {

		series = append(series, chart.TimeSeries{
			Name: yValue.Name,
			Style: chart.Style{
				// 随机渲染线条颜色
				StrokeColor: drawing.Color{
					R: uint8(rand.Intn(colorMultiplier)),
					G: uint8(rand.Intn(colorMultiplier)),
					B: uint8(rand.Intn(colorMultiplier)),
					A: uint8(colorMultiplier - 1), // 透明度
				},

			},
			XValues: xValues,
			YValues: yValue.Values,
		})

		var annotations []chart.Value2

		for index, y := range yValue.Values {
			annotations =  append(annotations, chart.Value2{
				Label:  strconv.FormatFloat(y, 'f', -1, 64),
				XValue: getNsec(xValues[index]),
				YValue: y,
			})
		}

		series = append(series, chart.AnnotationSeries{
			Annotations: annotations,
		})

	}

	// 3、新建图形
	graph := chart.Chart{
		Title:      title,
		Background: lineChartStyle,
		Width:      lineChartWidth,
		Height:     lineChartHeight,
		XAxis: chart.XAxis{
			Name:           lineChartXAxisName,
			ValueFormatter: timeFormat,
			Ticks:          ticks,
			Style: chart.Style{
				TextRotationDegrees: 45.0,
			},

		},

		YAxis: chart.YAxis{
			Name: lineChartYAxisName,
		},
		Series: series,
	}
	graph.Elements = []chart.Renderable{
		chart.LegendLeft(&graph),
	}

	// 4、输出目标
	img, err = writeLineChart(&graph)


	return
}

// getNsec 获取纳秒数
func getNsec(cur time.Time) float64 {
	return float64(cur.Unix() * int64(time.Second))
}

func writeLineChart(c *chart.Chart) (img string, err error) {
	var imgContent bytes.Buffer
	err = c.Render(chart.PNG, &imgContent)
	if err != nil {
		return
	}

	fo, err := os.Create("output.png")
	if err != nil {
		panic(err)
	}

	if _, err := fo.Write(imgContent.Bytes()); err != nil {
		panic(err)
	}

	//img = imgToStr(imgContent)

	return
}

func imgToStr(imgContent bytes.Buffer) string {
	return imgStrPrefix + base64.StdEncoding.EncodeToString(imgContent.Bytes())
}

func main() {
	/*//var b float64
	//b = 1000
	test := []float64{244, 288, 100, 150, 300, 190}
	ts1 := chart.ContinuousSeries{ //TimeSeries{
		Name:    "Time Series",
		//XValues: []float64{10 * b, 20 * b, 30 * b, 40 * b, 50 * b, 60 * b, 70 * b, 80 * b},
		XValues: test,
		YValues: test,
		//YValues: []float64{1.0, 2.0, 30.0, 4.0, 50.0, 6.0, 7.0, 88.0},
	}

	//ts2 := chart.ContinuousSeries{ //TimeSeries{
	//	Style: chart.Style{
	//		StrokeColor: chart.GetDefaultColor(1),
	//	},
	//
	//	XValues: []float64{10 * b, 20 * b, 30 * b, 40 * b, 50 * b, 60 * b, 70 * b, 80 * b},
	//	YValues: []float64{15.0, 52.0, 30.0, 42.0, 50.0, 26.0, 77.0, 38.0},
	//}

	graph := chart.Chart{

		XAxis: chart.XAxis{
			Name:           "The XAxis",
			ValueFormatter: chart.TimeMinuteValueFormatter, //TimeHourValueFormatter,
		},

		YAxis: chart.YAxis{
			Name: "The YAxis",
		},

		Series: []chart.Series{
			ts1,
			//ts2,
		},

		//Background: chart.Style{
		//	FillColor: drawing.Color{R: 0, G: 0, B: 0, A: 1},
		//},
		//Canvas: chart.Style{
		//	FillColor: drawing.Color{R: 0, G: 0, B: 0, A: 1},
		//},
	}

	buffer := bytes.NewBuffer([]byte{})
	err := graph.Render(chart.PNG, buffer)
	if err != nil {
		log.Fatal(err)
	}

	fo, err := os.Create("output.png")
	if err != nil {
		panic(err)
	}

	if _, err := fo.Write(buffer.Bytes()); err != nil {
		panic(err)
	}*/

	tests := []struct {
		title     string
		endTime   time.Time
		barValues []LineYValue
	}{
		{"line chart", time.Now(), []LineYValue{
			{"asd", []float64{278, 279, 300, 100, 200, 6, 700, 500, 200, 100, 180, 600, 500, 456}},

			},
		},
	}

	for _, test := range tests {
		createLineChart(test.title, test.endTime, test.barValues)
	}

}
